/******************************************************
* AlphaScale ASAP18xx BootCode
*  
* usb_define.h 
*  
* USB Header file
* 
* Copyright (C) 2009 AlphaScale Inc.
* He Yong <hoffer@sjtu.org>
* Ding Xiaopeng <dingxiaopeng@alpscale.cn>
* 
* ------------------- Modifications  ------------------
* Create File,                                    
*     He Yong, Ding Xiaopeng 2007-04-29       
******************************************************/

#ifndef __USB_DEFINE_H__
#define __USB_DEFINE_H__


#define USB_EP1_MAX_PACKET_SIZE_SETV 1
#define USB_EP1_MAX_PACKET_SIZE (8<<USB_EP1_MAX_PACKET_SIZE_SETV)


//#if CONFIG_USB_HIGH_SPEED
//#define USB_EP2_MAX_PACKET_SIZE_SETV 6 /* set value n = 2^(n+3) Byte, the best case so far is 6*/
//#else
#define USB_EP2_MAX_PACKET_SIZE_SETV 3
//#endif

#define USB_EP2_MAX_PACKET_SIZE (8<<USB_EP2_MAX_PACKET_SIZE_SETV)

/* set fifo size the same as package size*/
#define USB_EP2_MAX_FIFO_SIZE_SETV      USB_EP2_MAX_PACKET_SIZE_SETV  

#define USB_EP2_MAX_FIFO_SIZE           (8<<USB_EP2_MAX_FIFO_SIZE_SETV) 

#define EP0_FIFO_OFFSET 128
#define USB_EP2_TX_FIFO_ADDR (EP0_FIFO_OFFSET)
#define USB_EP2_RX_FIFO_ADDR (USB_EP2_TX_FIFO_ADDR + (8<<USB_EP2_MAX_FIFO_SIZE_SETV))

void usb_wait_for_completion(int * lock);


/*
//global variable
extern CONTROL_XFER *CtrlData;
extern unsigned char * State;
extern unsigned char * config_status;
*/

//macro operation
#define MSB(x) ( ((x)>>8) & 0xff )
#define LSB(x) ( (x) & 0xff )
#define SWAP(x) ( (((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF) )
#define SWAP32(x)   ((((u32)x)>>24) | ((((u32)x)>>8)&0xff00) | ((((u32)x)<<8)&0xff0000) | (((u32)x)<<24))

#define check_u8reg_assert(reg,i) ( (reg&(1<<i)) !=0 )
#define check_u16reg_assert(reg,i) ( (reg&(1<<i)) !=0 )

#define check_u8reg_deassert(reg,i) ( (reg&(1<<i)) ==0 )
#define check_u16reg_deassert(reg,i) ( (reg&(1<<i)) ==0 )


#define set_charreg(reg,i)\
do { reg|=(1<<i); } while(0)

#define set_shortreg(reg,i)         do { reg|=(1<<i); } while(0)
#define set_intreg(reg,i)           do { reg|=(1<<i); } while(0)
#define clr_charreg(reg,i)          do { reg&=(~(1<<i)); } while(0)  
#define clr_shortreg(reg,i)         do { reg&=(~(1<<i)); } while(0)  
#define clr_intreg(reg,i)           do { reg&=(~(1<<i)); } while(0)  

#define USB_ENDPOINT_DIRECTION_MASK				0x80
#define DEVICE_ADDRESS_MASK 					0x7f

#define USB_DEVICE_DESCRIPTOR_TYPE       		0x01
#define USB_CONFIGURATION_DESCRIPTOR_TYPE		0x02
#define USB_STRING_DESCRIPTOR_TYPE       		0x03
#define USB_INTERFACE_DESCRIPTOR_TYPE    		0x04
#define USB_ENDPOINT_DESCRIPTOR_TYPE     		0x05
#define USB_POWER_DESCRIPTOR_TYPE        		0x06

#define USB_CONFIGURATION_ONLY                  0x0009
#define USB_CONFIGURATION_ALL                   0x00ff
#define USB_CONFIGURATION_ALL_SECOND            0x2e00//--xiaozi

#define USB_REQUEST_TYPE_MASK    				(unsigned char)0x7f
#define USB_REQUEST_MASK         				(unsigned char)0xFF
#define USB_STANDARD_REQUEST     				(unsigned char)0x00
#define USB_VENDOR_REQUEST       				(unsigned char)0x40

#define EP0_IDLE	0
#define EP0_TX		1//global constant
#define EP0_RX		2
#define MAX_CONTROLDATA_SIZE 64	//64 byte for max

#define ep0_MaxP 	64
#define USB_DMA_IRQ     11

#define USB_MC_IRQ      57

#define USB_NEGEDGE_IRQ 59
//descriptor data structure definition
#define USB_POSEDGE_IRQ 60
typedef unsigned char UCHAR;
#define PRIORITY_BASE   0x80000060
typedef unsigned short USHORT;
//typedef unsigned long u32;--xiaozi



typedef struct _USB_DEVICE_DESCRIPTOR
{

    UCHAR bLength;

    UCHAR bDescriptorType;
    UCHAR bcdUSB1;
    UCHAR bcdUSB0;
    UCHAR bDeviceClass;
    UCHAR bDeviceSubClass;
    UCHAR bDeviceProtocol;
    UCHAR bMaxPacketSize0;
    UCHAR idVendor1;
    UCHAR idVendor0;
    UCHAR idProduct1;
    UCHAR idProduct0;
    UCHAR bcdDevice1;
    UCHAR bcdDevice0;
    UCHAR iManufacturer;
    UCHAR iProduct;
    UCHAR iSerialNumber;
    UCHAR bNumConfigurations;
}PACKED USB_DEVICE_DESCRIPTOR;

typedef struct _USB_CONFIGURATION_DESCRIPTOR
{
    UCHAR bLength;
    UCHAR bDescriptorType;
    //USHORT wTotalLength;
    UCHAR wTotalLength1;
    UCHAR wTotalLength0;//--XIAOZI
    UCHAR bNumInterfaces;
    UCHAR bConfigurationValue;
    UCHAR iConfiguration;
    UCHAR bmAttributes;
    UCHAR MaxPower;
}PACKED USB_CONFIGURATION_DESCRIPTOR;

typedef struct _USB_INTERFACE_DESCRIPTOR
{
    UCHAR bLength;
    UCHAR bDescriptorType;
    UCHAR bInterfaceNumber;
    UCHAR bAlternateSetting;
    UCHAR bNumEndpoints;
    UCHAR bInterfaceClass;
    UCHAR bInterfaceSubClass;
    UCHAR bInterfaceProtocol;
    UCHAR iInterface;
}PACKED USB_INTERFACE_DESCRIPTOR;

typedef struct _USB_ENDPOINT_DESCRIPTOR
{
    UCHAR bLength;
    UCHAR bDescriptorType;
    UCHAR bEndpointAddress;
    UCHAR bmAttributes;
    UCHAR wMaxPacketSize1;
    UCHAR wMaxPacketSize0;
    UCHAR bInterval;
}PACKED USB_ENDPOINT_DESCRIPTOR;

typedef struct _USB_HID_DESCRIPTOR
{
    UCHAR bLength;
    UCHAR bDescriptorType;
    USHORT bcdHID;
    UCHAR bCountryCode;
    UCHAR bNumDescriptors;
    UCHAR bDescriptorType2;
    USHORT wItemLength;
}PACKED USB_HID_DESCRIPTOR;


//usb command structure
typedef struct _device_request
{
    unsigned char bmRequestType;
    unsigned char bRequest;
    unsigned short wValue;
    unsigned short wIndex;
    unsigned short wLength;
}PACKED DEVICE_REQUEST;

//data buffer structure
typedef struct _control_xfer
{
    DEVICE_REQUEST DeviceRequest;   //if ep0 get setup packet, stored in this buffer structure
    unsigned short wLength;         //total length to be dealed with(dont change in one transmit)
    unsigned short wCount;          //how many bytes have been dealed with
    unsigned char * pData;          //the pt of the data to be transmited
    unsigned char dataBuffer[MAX_CONTROLDATA_SIZE]; //if ep0 get data packet, stored in this buffer structure
}PACKED CONTROL_XFER;

/**************
*   String Descriptors...  redefine to suit device application.
*/
#define UNICODE_LANGUAGE_STR_ID  (0)    /* Index values */
#define MANUFACTURER_STR_ID      (1)
#define PRODUCT_NAME_STR_ID      (2)
#define SERIAL_NUM_STR_ID        (3)
#define UNICODE_ENGLISH     (0x0409)    /* US_English (Ref: USB_LANGIDs.pdf) */

struct USB_STRING_DESCR_LANG
{
    uchar  bLength;        /* Size of descriptor */
    uchar  bDescrType;     /* Type of descriptor (ie. STRING) */
    ushort wLangID;        /* Language code (16b word) */
}PACKED ;

struct USB_STRING_DESCR_MANU
{
    uchar  bLength;        /* Size of descriptor */
    uchar  bDescrType;     /* Type of descriptor (ie. STRING) */
    uchar  bString[16];    /* UNICODE string [chars X2] */
}PACKED ;

struct USB_STRING_DESCR_PROD
{
    uchar  bLength;        /* Size of descriptor */
    uchar  bDescrType;     /* Type of descriptor (ie. STRING) */
    uchar  bString[24];    /* UNICODE string [chars X2] */
}PACKED ;

struct USB_STRING_DESCR_SNUM
{
    uchar  bLength;        /* Size of descriptor */
    uchar  bDescrType;     /* Type of descriptor (ie. STRING) */
    uchar  bString[16];    /* UNICODE string [chars X2] */
}PACKED ;


typedef struct __all_descriptor__{
    USB_DEVICE_DESCRIPTOR           dev_dscrp;
    USB_CONFIGURATION_DESCRIPTOR    config_dscrp;
    USB_INTERFACE_DESCRIPTOR        interface_dscrp;
    USB_ENDPOINT_DESCRIPTOR         ep2i_dscrp;
    USB_ENDPOINT_DESCRIPTOR         ep2o_dscrp;
    USB_ENDPOINT_DESCRIPTOR         ep1i_dscrp;
    USB_ENDPOINT_DESCRIPTOR         ep1o_dscrp;
    struct USB_STRING_DESCR_LANG           string_lang_dscrp;
    struct USB_STRING_DESCR_MANU           string_manu_dscrp;
    struct USB_STRING_DESCR_PROD           string_prod_dscrp;
    struct USB_STRING_DESCR_SNUM           string_sn_dscrp;
}PACKED USB_ALL_DESCRIPTOR;


#define NUM_ENDPOINTS 4                                                                                                                                                                          
#define CONFIG_DESCRIPTOR_LENGTH    sizeof(USB_CONFIGURATION_DESCRIPTOR)+sizeof(USB_INTERFACE_DESCRIPTOR)+(NUM_ENDPOINTS * sizeof(USB_ENDPOINT_DESCRIPTOR))//+sizeof(USB_HID_DESCRIPTOR)  

//#ifdef ARM
//used for ARM interrupt mask

#define setindex(ep_num)   outb(ep_num,USB0_Index)


//global variable, for ordinary variable will be deleted after exit the sub-routine
extern volatile CONTROL_XFER CtrlData;
extern unsigned char USB_State;
extern unsigned char USB_configuration;
extern unsigned char unregcommand;

extern unsigned char EP_BUFFER[USB_EP2_MAX_PACKET_SIZE];  // EP0, EP2 buffer 

#define ADDR_NO_CHANGE      0
#define ADDR_READY_TO_SET   1
#define ADDR_WAIT_INT       2

extern unsigned char address_to_be_set;    
extern unsigned char address_status;


#define REMULATE_USB_HS 1
#define REMULATE_USB_FS 0
//void usb_init(char * info_buf,int type);
void usb_isr(void);
void usb_isr_main(void);
void ep2_tx(void);
void ep2_rx(void);
void ep0_isr(void);


void get_status            (void);
void clear_feature     (void);
void set_feature           (void);
void set_address           (void);
void get_descriptor        (void);
void get_configuration (void);        
void set_configuration (void);        
void get_interface     (void);
void set_interface     (void);
void reserved          (void);
void discon_usb(void);                                                    
void con_usb(void);                                                       
void recon_usb(void);                                                     
void usb_handler(void);                                                       
unsigned char LoadFifo(volatile unsigned char* buf , unsigned char len);  
unsigned char UnloadFifo(volatile unsigned char* buf , unsigned char len);

unsigned int loadfifo(char *a,unsigned int le);
unsigned int unloadfifob(char *a,unsigned int le);  

void ep0_isr(void);                                                       
void ep0_routine(void);                                                   
void IDLE(unsigned short CSR0_reg);                             
void TX(void);                                                            
void RX(void);      
void ep2_tx(void);                                                      
void ep2_rx(void);
int service_bulk_send(void);
int service_bulk_rec(void);
void usb_ransfer_status_init(void);

void check_usb_set_address(void);
void audio_reference_init(void);

#define usb_dbg(msg) if(0) puts(msg);

#endif //__USB_DEFINE_H__

